#include<poll.h>
#include"Sock.hpp"
using namespace std;

#define INVALID_FD -1
#define NUM 128 

void Usage(std::string proc)
{
  cout <<"USage\n\t" << proc <<" " << "port" << endl;
  exit(1);
}
// ./poll port启动poll服务器
int main(int argc,char* argv[])
{
  if(argc != 2)
  {
    Usage(argv[0]);
  }
  uint16_t port = atoi(argv[1]);
  int listen_sock = Sock::Socket();
  Sock::Bind(listen_sock,port);
  Sock::Listen(listen_sock);
  
  struct pollfd pollfds[NUM]; 
  /*
   * struct pollfd 
   * {
   *    int fd;
   *    short events;
   *    short revents
   * };
  */ 

  //将监听套接字放到数组的0下标位置
  pollfds[0].fd = listen_sock;
  pollfds[0].events = POLLIN; //关注监听套接字上的读取是否就绪
  pollfds[0].revents = 0;

  //将数组其他位置置为无效位置
  for(int i = 1;i<NUM;i++)
  {
    pollfds[i].fd = INVALID_FD;
    pollfds[i].events = 0;
    pollfds[i].revents = 0;
  }

  for(;;)
  {
    int n = poll(pollfds,NUM,-1);//阻塞等待,直到被监视的某个fd上有事件就绪
    switch(n)
    {
      case 0:
        cout << "timeout超时!!!" << endl;    
        break;
      case -1:
        cerr << "poll failed !!!" << endl;
        break;
      default: //有文件描述符上的事件就绪,轮询检测是哪个fd
        for(int i = 0;i<NUM;i++)
        {
          if(pollfds[i].fd == INVALID_FD)
            continue;
          
          //当前pollfds[i].fd上有事件就绪,判断是监听套接字 / 与客户端建立连接的套接字
          if(pollfds[i].fd == listen_sock && pollfds[i].revents & POLLIN)
          {
            //监听套接字上的读事件就绪
            int sock = Sock::Accept(listen_sock);
            cout <<"listen_sock上有新连接到来！！,new_sock:" << sock << endl;
            int pos = 1;
            for(;pos < NUM;pos++)
            {
              if(pollfds[pos].fd == INVALID_FD)
              {
                break;
              }
            }
            //case1:pos == NUM 
            //case2:pos < NUM 
            if(pos == NUM)
            {
              cout <<"服务器已经满载....舍弃该条连接"<<endl;
              close(sock);
            }
            else 
            {
              cout <<"新连接被放到pollfds数组的" << pos <<"位置" << endl;
              pollfds[pos].fd = sock;
              pollfds[pos].events = POLLIN;
              pollfds[pos].revents = 0;
            }
          }
          else if(pollfds[i].revents & POLLIN) //与客户端建立连接的读事件就绪
          {
            //此时可以读取该客户端发来的内容，因为读取已经就绪，所以不会阻塞
            cout <<"sock: " <<pollfds[i].fd <<" 中有读取事件就绪,可以读取啦！！！" << endl;
            
            char buf[1024] = {0};
            ssize_t n = read(pollfds[i].fd,buf,sizeof(buf)-1);
            if(n > 0)
            {
              buf[n] = 0;
              cout <<"client:" << pollfds[i].fd <<"#" << buf << endl;
            }
            else if(n == 0)
            {
              cout << "sock" <<pollfds[i].fd <<"关闭了连接,client quit！！" << endl;
              close(pollfds[i].fd);
              cout <<"已将sock:" << pollfds[i].fd <<"在pollfds数组中" << i <<"位置移除 " << endl;
              pollfds[i].fd = INVALID_FD ;
              pollfds[i].revents = 0;
              pollfds[i].events = 0;
            }
            else  //n < 0
            {
              cout << "sock:" <<pollfds[i].fd <<" 中读取错误！！" << endl;
              close(pollfds[i].fd);
              cout <<"已将sock:" << pollfds[i].fd <<"在pollfds数组中" << i <<"位置移除 " << endl;
              pollfds[i].fd = INVALID_FD ;
              pollfds[i].revents = 0;
              pollfds[i].events = 0;
            }
          }
        }
        break;
    }
  }
  close(listen_sock);
  return 0;
}
